{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  Deep Neural Network (DNN) \n",
    "\n",
    "### Regularization of DNN [256,256,256,256] with l2 regularization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Get the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Stored variables and their in-db values:\n",
      "X_32test_std              -> defaultdict(<class 'list'>, {0: array([[ 0.7957011\n",
      "X_32train_std             -> array([[-0.44445615,  0.62874736, -0.19049071, ...\n",
      "X_test                    -> defaultdict(<class 'list'>, {0: array([[[-0.004097\n",
      "X_test_std                -> defaultdict(<class 'list'>, {0: array([[ 0.8784659\n",
      "X_train                   -> array([[[-0.00304779,  0.0030504 , -0.00249425, ..\n",
      "X_train_std               -> array([[-0.44445615,  0.62874736, -0.19049071, ...\n",
      "snrs                      -> [-20, -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, \n",
      "y_32_test                 -> defaultdict(<class 'list'>, {0: array([6, 7, 1, ..\n",
      "y_32_train                -> array([7, 2, 4, ..., 5, 5, 3])\n",
      "y_test                    -> defaultdict(<class 'list'>, {0: array([3, 2, 5, ..\n",
      "y_train                   -> array([7, 2, 4, ..., 5, 5, 3])\n"
     ]
    }
   ],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from collections import defaultdict\n",
    "from time import time\n",
    "from functools import partial\n",
    "\n",
    "%store -r\n",
    "%store"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training data:  (80000, 32) and labels:  (80000,)\n",
      " \n",
      "Test data:\n",
      "Total 20 (4000, 32) arrays for SNR values:\n",
      "[-20, -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18]\n"
     ]
    }
   ],
   "source": [
    "print(\"Training data: \", X_32train_std.shape, \"and labels: \", y_32_train.shape)\n",
    "print(\" \")\n",
    "print(\"Test data:\")\n",
    "print(\"Total\", len(X_32test_std), X_32test_std[18].shape, \"arrays for SNR values:\")\n",
    "print(sorted(X_32test_std.keys()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# tf.reset_default_graph()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create validation set required for early stopping"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Validation set data (40000, 32) and labels (40000,)\n"
     ]
    }
   ],
   "source": [
    "X_val = []\n",
    "y_val = []\n",
    "\n",
    "X_test_new = defaultdict(list)\n",
    "y_test_new = defaultdict(list)\n",
    "\n",
    "for snr in snrs:\n",
    "    n_test = X_32test_std[snr].shape[0]\n",
    "    X_val.append(X_32test_std[snr][:(n_test*0.5)])\n",
    "    y_val.append(y_32_test[snr][:(n_test*0.5)])\n",
    "    X_test_new[snr] = X_32test_std[snr][(n_test*0.5):]\n",
    "    y_test_new[snr] = y_32_test[snr][(n_test*0.5):]\n",
    "    \n",
    "X_val = np.vstack(np.asarray(X_val))\n",
    "y_val =np.hstack(np.asarray(y_val))\n",
    "\n",
    "print(\"Validation set data\", X_val.shape, \"and labels\", y_val.shape)\n",
    "\n",
    "X_32test_std = X_test_new\n",
    "y_32_test = y_test_new\n",
    "X_32_val = X_val \n",
    "y_32_val = y_val"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Design and train the DNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\tValidation loss: 1.399964\tMinimum loss: 1.399964\tAccuracy on validation set: 0.43\n",
      "1\tValidation loss: 1.325026\tMinimum loss: 1.325026\tAccuracy on validation set: 0.45\n",
      "2\tValidation loss: 1.303501\tMinimum loss: 1.303501\tAccuracy on validation set: 0.46\n",
      "3\tValidation loss: 1.273262\tMinimum loss: 1.273262\tAccuracy on validation set: 0.48\n",
      "4\tValidation loss: 1.238810\tMinimum loss: 1.238810\tAccuracy on validation set: 0.49\n",
      "5\tValidation loss: 1.211447\tMinimum loss: 1.211447\tAccuracy on validation set: 0.50\n",
      "6\tValidation loss: 1.204828\tMinimum loss: 1.204828\tAccuracy on validation set: 0.50\n",
      "7\tValidation loss: 1.189813\tMinimum loss: 1.189813\tAccuracy on validation set: 0.51\n",
      "8\tValidation loss: 1.207989\tMinimum loss: 1.189813\tAccuracy on validation set: 0.50\n",
      "9\tValidation loss: 1.185495\tMinimum loss: 1.185495\tAccuracy on validation set: 0.51\n",
      "10\tValidation loss: 1.180001\tMinimum loss: 1.180001\tAccuracy on validation set: 0.51\n",
      "11\tValidation loss: 1.179442\tMinimum loss: 1.179442\tAccuracy on validation set: 0.51\n",
      "12\tValidation loss: 1.176682\tMinimum loss: 1.176682\tAccuracy on validation set: 0.51\n",
      "13\tValidation loss: 1.178056\tMinimum loss: 1.176682\tAccuracy on validation set: 0.51\n",
      "14\tValidation loss: 1.173387\tMinimum loss: 1.173387\tAccuracy on validation set: 0.51\n",
      "15\tValidation loss: 1.171380\tMinimum loss: 1.171380\tAccuracy on validation set: 0.51\n",
      "16\tValidation loss: 1.174501\tMinimum loss: 1.171380\tAccuracy on validation set: 0.51\n",
      "17\tValidation loss: 1.170430\tMinimum loss: 1.170430\tAccuracy on validation set: 0.51\n",
      "18\tValidation loss: 1.177940\tMinimum loss: 1.170430\tAccuracy on validation set: 0.51\n",
      "19\tValidation loss: 1.170121\tMinimum loss: 1.170121\tAccuracy on validation set: 0.51\n",
      "20\tValidation loss: 1.164718\tMinimum loss: 1.164718\tAccuracy on validation set: 0.51\n",
      "21\tValidation loss: 1.160551\tMinimum loss: 1.160551\tAccuracy on validation set: 0.51\n",
      "22\tValidation loss: 1.161600\tMinimum loss: 1.160551\tAccuracy on validation set: 0.51\n",
      "23\tValidation loss: 1.165535\tMinimum loss: 1.160551\tAccuracy on validation set: 0.51\n",
      "24\tValidation loss: 1.163520\tMinimum loss: 1.160551\tAccuracy on validation set: 0.51\n",
      "25\tValidation loss: 1.168594\tMinimum loss: 1.160551\tAccuracy on validation set: 0.51\n",
      "26\tValidation loss: 1.177858\tMinimum loss: 1.160551\tAccuracy on validation set: 0.51\n",
      "27\tValidation loss: 1.168509\tMinimum loss: 1.160551\tAccuracy on validation set: 0.51\n",
      "28\tValidation loss: 1.160434\tMinimum loss: 1.160434\tAccuracy on validation set: 0.52\n",
      "29\tValidation loss: 1.171907\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "30\tValidation loss: 1.168555\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "31\tValidation loss: 1.165855\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "32\tValidation loss: 1.166033\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "33\tValidation loss: 1.164038\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "34\tValidation loss: 1.176813\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "35\tValidation loss: 1.172424\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "36\tValidation loss: 1.164878\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "37\tValidation loss: 1.164773\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "38\tValidation loss: 1.165540\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "39\tValidation loss: 1.168147\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "40\tValidation loss: 1.170789\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "41\tValidation loss: 1.178842\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "42\tValidation loss: 1.171219\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "43\tValidation loss: 1.174783\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "44\tValidation loss: 1.166952\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "45\tValidation loss: 1.166195\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "46\tValidation loss: 1.177455\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "47\tValidation loss: 1.177518\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "48\tValidation loss: 1.187795\tMinimum loss: 1.160434\tAccuracy on validation set: 0.51\n",
      "** EARLY STOPPING ** \n",
      " \n",
      "INFO:tensorflow:Restoring parameters from ./DNN4layer_regtech_l2\n",
      "Training and testing took 1.738209 minutes\n"
     ]
    }
   ],
   "source": [
    "# ----------------- Initialize parameters -----------------------\n",
    "\n",
    "\n",
    "n_hidden1 = 256\n",
    "n_hidden2 = 256\n",
    "n_hidden3 = 256\n",
    "n_hidden4 = 256\n",
    "\n",
    "n_outputs = 8\n",
    "\n",
    "X = tf.placeholder(tf.float32, shape=(None, 32))\n",
    "y = tf.placeholder(tf.int64, shape=(None))\n",
    "training_ = tf.placeholder_with_default(False, shape=[])\n",
    "\n",
    "weight_init = tf.contrib.layers.xavier_initializer()\n",
    "activation_func = tf.nn.elu\n",
    "\n",
    "# ------------------- Define layers -----------------------\n",
    "\n",
    "from tensorflow.contrib.layers import fully_connected\n",
    "\n",
    "scale_val = 0.001\n",
    "new_dense_layer = partial(tf.layers.dense, kernel_initializer = weight_init,\n",
    "                          kernel_regularizer = tf.contrib.layers.l2_regularizer(scale_val), \n",
    "                          activation = activation_func)\n",
    "\n",
    "dense_layer1 = new_dense_layer(X, n_hidden1)\n",
    "\n",
    "dense_layer2 = new_dense_layer(dense_layer1, n_hidden2)\n",
    "\n",
    "dense_layer3 = new_dense_layer(dense_layer2, n_hidden3)\n",
    "\n",
    "dense_layer4 = new_dense_layer(dense_layer3, n_hidden4)\n",
    "\n",
    "logits = tf.layers.dense(dense_layer4, n_outputs)\n",
    "\n",
    "# ----------------- Specify performance measure ----------------------\n",
    "\n",
    "xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)\n",
    "loss = tf.reduce_mean(xentropy)\n",
    "\n",
    "optimizer = tf.train.AdamOptimizer()\n",
    "training_op = optimizer.minimize(loss)\n",
    "\n",
    "correct = tf.nn.in_top_k(logits, y, 1)\n",
    "accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))\n",
    "        \n",
    "# ------------------ Execution phase ----------------------------------    \n",
    "\n",
    "n_epochs = 1000\n",
    "batch_size = 1024\n",
    "n_train = X_train_std.shape[0]\n",
    "n_iter = n_train//batch_size\n",
    "\n",
    "saver = tf.train.Saver()\n",
    "\n",
    "min_loss = np.infty\n",
    "epochs_without_improvement = 0 \n",
    "max_epochs_without_improvement = 20   \n",
    "\n",
    "acc_test = defaultdict(list)\n",
    "\n",
    "start = time()\n",
    "path = \"./DNN4layer_regtech_l2\"\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    tf.global_variables_initializer().run()\n",
    "    for epoch in range(n_epochs):\n",
    "        for iteration in range(n_iter):\n",
    "            rand_indices = np.random.choice(n_train,batch_size) #select random samples to form mini batches   \n",
    "            X_batch, y_batch = X_32train_std[rand_indices], y_32_train[rand_indices]\n",
    "            sess.run(training_op, feed_dict={X: X_batch, y: y_batch,  training_: True})\n",
    "        valid_loss, acc_val = sess.run([loss, accuracy], feed_dict={X: X_32_val, y: y_32_val, training_: True})\n",
    "        \n",
    "        # Early stopping \n",
    "        \n",
    "        if valid_loss < min_loss:\n",
    "            save_path = saver.save(sess, path)\n",
    "            min_loss = valid_loss\n",
    "            epochs_without_improvement = 0\n",
    "        else:\n",
    "            epochs_without_improvement += 1\n",
    "            if epochs_without_improvement > max_epochs_without_improvement:\n",
    "                print(\"** EARLY STOPPING ** \")\n",
    "                break\n",
    "        print(\"{}\\tValidation loss: {:.6f}\\tMinimum loss: {:.6f}\\tAccuracy on validation set: {:.2f}\".format(\n",
    "            epoch, valid_loss, min_loss, acc_val))\n",
    "\n",
    "print(\" \")\n",
    "with tf.Session() as sess:\n",
    "    saver.restore(sess, path)\n",
    "    for snr in snrs:\n",
    "        acc_test[snr] = accuracy.eval(feed_dict={X: X_32test_std[snr], y: y_32_test[snr]})\n",
    "\n",
    "print(\"Training and testing took %f minutes\"%(float(time() - start)/60))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Test the DNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "DNN's test accuracy on -20 dB SNR samples =  0.119\n",
      "DNN's test accuracy on -18 dB SNR samples =  0.1245\n",
      "DNN's test accuracy on -16 dB SNR samples =  0.128\n",
      "DNN's test accuracy on -14 dB SNR samples =  0.127\n",
      "DNN's test accuracy on -12 dB SNR samples =  0.14\n",
      "DNN's test accuracy on -10 dB SNR samples =  0.19\n",
      "DNN's test accuracy on -8 dB SNR samples =  0.292\n",
      "DNN's test accuracy on -6 dB SNR samples =  0.3805\n",
      "DNN's test accuracy on -4 dB SNR samples =  0.4115\n",
      "DNN's test accuracy on -2 dB SNR samples =  0.466\n",
      "DNN's test accuracy on 0 dB SNR samples =  0.558\n",
      "DNN's test accuracy on 2 dB SNR samples =  0.676\n",
      "DNN's test accuracy on 4 dB SNR samples =  0.8085\n",
      "DNN's test accuracy on 6 dB SNR samples =  0.8285\n",
      "DNN's test accuracy on 8 dB SNR samples =  0.841\n",
      "DNN's test accuracy on 10 dB SNR samples =  0.83\n",
      "DNN's test accuracy on 12 dB SNR samples =  0.8355\n",
      "DNN's test accuracy on 14 dB SNR samples =  0.8325\n",
      "DNN's test accuracy on 16 dB SNR samples =  0.834\n",
      "DNN's test accuracy on 18 dB SNR samples =  0.8425\n"
     ]
    }
   ],
   "source": [
    "for snr in snrs:\n",
    "    print(\"DNN's test accuracy on %d dB SNR samples = \"%(snr), acc_test[snr])   "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "##  Visualize DNN's performance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmMAAAGPCAYAAAAQptcZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3Xl4VPXZ//H3nckCYQsSBTdI1OJWlbpVq7W02kpbW+tS\nKy0VrIhtUdQ+KIq2SrW4oaWovz5FrEuxUru4dXFpFa0+WGld6gKikoAgiGGHQDKZuX9/zASGZDIZ\nILOd+byuay7mnDlzPt8zKLlzvvecY+6OiIiIiORGSa4HICIiIlLMVIyJiIiI5JCKMREREZEcUjEm\nIiIikkMqxkRERERySMWYiIiISA6pGBMpImZ2qJk9ZGbvm9lmM2sws7fj605ts2004fFQm9cuSHjt\nJwnrr2nzvmg8p87MZpjZXtk61u3R5niiZnZDrsckIsVDxZhIkTCz44G5wJlADVAG9AX2B84Avprk\nba0XIjzdzA5J8Xqy9a2PMmAg8D3gBTOr3MFDyKTvsO2Yv5Pb4YhIMVExJlI8JhArjCLAqUAPYBfg\n08BPgYUp3mvApO3Mm+TuIeAgYHF83d7x7LxhZoOA4xJXAXua2dDcjCh9ZlaR6zGIyM5TMSZSPD4R\n/3M98LS7b3b3te7+b3ef5O43dvC+FmIFyqlmNmR7Q939HeBPCasGptrezB6OTxW2mNmAhPVmZh/G\nX1sYX9fNzG4ws/lmtt7MNsSnYP9gZkenOcTvEjs+gF8nrB/RwfhON7On4lO8TWa2xMz+aGZ9Erbp\nb2Y/N7N3zGyTma01s/+Y2XcTtmmdEn2mzf7brW8z/fsNM7vbzBqATfHXv2Bmf45PB6+Pj2uxmf3G\nzPZNcgyfN7NHzGx5fNvlZvZXM6s1s8MSsu5s876LEl77Vpqfr4h0QsWYSPH4IP5nFfCumf3SzM4x\ns5pO3rcG+As7dnaslSU8X9HJtq0FkQGJP/CHAgOITSPeE193K7Ezfp8AKoHuxKZgTwOOTHNs347/\n2RLf17J49hltzzyZ2RTgD8BJxKZ4S4HdgW8AfeLb7Au8DlwM7AeUAz2BIcDn22SnmubtaP1dwKh4\nfjS+/ijgy8QK3cr4uPYkNt36opntknAMFwF/B74O7BrfdlfgZGBvd38deC6++XfaTCu3/n2sZNsC\nW0R2gooxkeIxldgPbwf2Ai4A7gUWmtmLZnZYive2NumfYmZHbE+omR1ArDgC2AA83slb/gosjz//\ndsL61udObNwAn40vv0SsoOgBHAD8EJiXxtiOiG/vwDPuvgp4OP5yb2IFS+u2RwE/im+7lljvXW9i\nBdClQGN809uB3eLb/YlYQdYLOAHY5izYTjiZWNHV+nf2VHz//YlNRfcDJsdf25X4WT4z2xO4Jb4+\nDIwhVtTtTqyn7+P4a1Pjf/Yi3j8X//LFsfHjut/dw110LCJFT8WYSJFw978AJwLPEjsLlNiwfizw\neJLmeou/91W2FlHpnh271syiwNvAIOA94Kvu3tDJOCPAb+LZR5rZPmZWBpzO1qKp9SxfXXy7g4gV\njCOIFSK/dvdn0xjjOQnP/9jmT9h2qvLrCc9vdfeH3X2juy9192nu3mBm3YidNYNY4XmOu9e5e6O7\nv+juM9MYU2emuPvf3b3J3d+Kr/uQWNE0B9gIrAKuSnjP/vE/hxE7Uwcw093vdvd17r7C3e9z99YC\n9jHgfWKf7ffj64az9Qzn3V1wHCISp2JMpIi4+3PufhJQTezbk/9L7AwJxKa1jm37loTn18T//DJw\nTDpxCQ+ITSGWd7z5NhJ7t74dz+wbX56R8NqlwMvEzlBdBEwH/g9YamYnkYKZlQBnJax6z8wOJjYF\nt5FY4TEsYYqvf8K2HZ1124XYtJ8Di919U6oxJBlTKI3NXmvzHiN2xu37wD7EPuPEzx1inz1sewxv\ndxTg7k7sDB/AkHj/XesU5b/cvcP3isj2UzEmUiTMrFfr8/jZkCfcfSxwX8Jmu7R/55b3vAY8QqxI\nSdrc3sYkoILYGZsIsWLv4XSuNRZv+n8pvjg8/oBY/9ojCdstdPdjgD2ALxLr01pG7OzY7aT2JWLF\niceP6RngDWLFTo/4NqXA2fHnHyW898AO9rmKrV94GBg/U9aR5vifidvs08mYId60n+DQ+HgceAsY\nFP8Wa7JvraZzDK1+DayLP78JODyeMT2NMYrIdlAxJlI8Hol/u+6rZlZtZqVm9klivUatOuuzupbY\nD+S0/u1w9xZ3nwW0fiuvJ9DRtzbb+jWxouYAYtdBc+ABd28tYjCz8WZ2FrEzPy8ADxGbsjM6+dYm\nsW9RbhlqBw/YWng+1hoL/MjMTjOzHma2h5ldaGbV7r4ZeDrhWO+Pf0Ox0sw+nfhtSmBRfF+HmNne\n8anY69P4XNpqSXjeBDTGL9cxMcm2TxArAg34rpl9z8z6mNmuZvZdM9tSoLn7Brb+HXwuvnoDsc9Y\nRLqQijGR4lFO7CzV48S+0dgM/JdYP5EDj7j7m23ek/gtSNz9DWI9Vcb2uY7YWRYDzjazQ9N4zyxi\nTfFG7AwVbP0WZauT49stBDYTOyt2BLHjeaKjHZtZD7aeOWoCqtw9lPgAlsazP21m+7r7XGLf3nRi\n35z8I7HLhCwBfkGsoR5gHFu/gHAmsd6rDcT6uRK/TflA/M8e8W3WAF9pHWKHn0p789laRB8BNBDr\npWs9y7llX+6+FLiM2Bc5SolN+a4mdsbsXmLN/ommsfVLHw486O6NiEiXUjEmUjyuJvYtubnEzh41\nE+uNehW4kq3Tca3aniFqdS2xace0L8vg7iuBKWydEuz0dkPxMzN/SBjD6/EvEiS6l9hlNz4gNn3X\nDLxLrGg6h46dTuxsmgOPuvv6JNvMpM3ZMXe/jNhZur8Tm5JsJla0PUzsG5a4+/vELmPxC2ABsSJx\nPfAKsS9PtLoRuC3+/iZil5M4jo4/92TrWr/w8DXgb8QK3o+J/T2PS7Yvd7+d2Bc5WovyMLFi7Am2\nXv6kddt64FG2FnSJ/Xoi0kUs1qcpIiKyrfgXCp4Fjgf+4+5H5XhIIoFU2vkmIiJSbMxsPrEvQvQj\ndmbt2pwOSCTAdGZMRETaMbMIsX6xxcCN7n5XjockElgqxkRERERySA38IiIiIjlUsD1jZqZTeiIi\nIlIw3D3pZWsK+syYu2ftcc011yhPeXmXpTzlKa948oJ8bMWQl0pBF2PZVF9frzzl5V2W8pSnvOLJ\nC/KxFUNeKirGRERERHIodO211+Z6DDtk0qRJ12Zz7FVVVdTU1ChPeXmVpTzlKa948oJ8bMWQN2nS\nJK699tpJyV4r2EtbmJkX6thFRESkuJgZHsQG/myaPXu28pSXd1nKU57yiicvyMdWDHmpqBgTERER\nySFNU4qIiIhkmKYpRURERPKUirE0BX0uW3mFmaU85SmvePKCfGzFkJeKijERERGRHFLPmIiIiEiG\nqWdMREREJE+pGEtT0OeylVeYWcpTnvKKJy/Ix1YMeamoGBMRERHJIfWMiYiIiGSYesZERERE8pSK\nsTQFfS5beYWZpTzlKa948oJ8bMWQl4qKMREREZEcUs+YiIiISIapZ0xEREQkT6kYS1PQ57KVV5hZ\nylOe8oonL8jHVgx5qagYExEREckh9YyJiIiIZJh6xkRERETylIqxNAV9Llt5hZmlPOUpr3jygnxs\nxZCXiooxERERkRxSz5iIiIhIhuVVz5iZDTOz+Wa2wMwmJHl9oJn93cxeN7NnzGyPbI9RREREJFuy\nWoyZWQlwB3AycDAw3MwOaLPZFOBedz8M+ClwYzbH2JGgz2UrrzCzlKc85RVPXpCPrRjyUsn2mbGj\ngXfdfZG7h4FZwKlttjkIeAbA3WcneV1EREQkMLLaM2ZmZwAnu/uY+PII4Gh3H5ewzUzgX+5+u5md\nDvweqHb31W32pZ4xERERKQipesZKsz2WJOvaVlSXAXeY2SjgeWAp0JJsZ6NGjaKmpgaAqqoqhgwZ\nwtChQ4Gtpx+1rGUta1nLWtaylrO93Pq8vr6eTrl71h7AMcATCctXABNSbN8DWNzBa55Nzz77rPKU\nl3dZylOe8oonL8jHVgx58bolab1T0nm51qXmAvuZ2SAzKwfOBh5L3MDM+plZ6xm0K4FfZ3mMIiIi\nIlmT9euMmdkw4BfEvjxwt7vfaGaTgLnu/ud4X9kNQJTYNOVYjzX7t92PZ3vsIiIiIjsiVc+YLvoq\nIiIikmF5ddHXQpXYkKc85eVLlvKUp7ziyQvysRVDXioqxkRERERySNOUIiIiIhmmaUoRERGRPKVi\nLE1Bn8tWXmFmKU95yiuevCAfWzHkpaJiTERERCSH1DMmIiIikmHqGRMRERHJUyrG0hT0uWzlFWaW\n8pSnvOLJC/KxFUNeKirGRERERHJIPWMiIiIiGaaeMREREZE8pWIsTUGfy1ZeYWYpT3nKi6mrq+f8\nsVdz/EnDOX/s1dTV1WclV/+2FF5erv5bSUXFmIiIFLS6unqGj7mZBc0j2NjjGyxoHsHwMTfnxQ9Z\nyS/vvVfH2efn338r6hkTEZGCdv7Yq1nQPIJQWeWWdZFwI/023cftt/2U3XYppaw0aatOQairq2fy\nlBk0rAlTXVXGxPGjqa2tyfGo8t/ctzfxwmubaFgbYeXaCA1rWvjPP25j4JAx7f5bGVw+k7vuvD6j\n40nVM1aa0WQREZEd5O6sXBvhg49aWLIivOXPFasj3DVxAGaxn2sNa8KE+lRu895QWSWvvrqJ7167\njLJS+OvUvQmVWLv9r9kQpapnyZZ95ZvWs34VNeMI9alkVXMjw8fczIPTL89YQZbt4i/dvCUrwry1\nsImGNZFYgbUmVmR97vBKzjqpd7vtFy4N8/gLG7Zd6dFtCjGI/bfSsCbcdQe0A1SMpWn27NkMHTpU\necrLqyzlKS9f81p/wM57530O3H/flD/QN26K0r3CKGlXLMF3r1lGU7j9LEjD2gi7VsV+hFVXlbGq\nuZFQWSWrl86h757HEgk30rd3KbvtEqIsZO0KMYA1G6KcMWEp3SqMPfqVsnt1KQOqSxnYv5SvfbZX\nlx1fW+6etPhbvDzMC681sr4xyoZNUdY3Rnl81h303GfcNsdWUTOOyVNmcNGlV3PP42upKDMqyo2K\nMqO83DhgUAWnHN+z3f4/XtPC/Prm2Pat7yk3evcI0a9PaMtxtRZ/6za8zqrKw7YUfzU1g4hEY38v\nyc40btwUpWFNhJaIE4lCJOK0RJzePUIM2r2s3fYfNrTw1PPvcNttt9P3wEu25J16zo08ev8V7T7P\n/8zbzC9+t7rdfpLtG+DIA7vRrbwv/fqE6FcVorpPiCuv6sm74fb/rVRXJd9HtqgYExGRLpX4A31j\nj9dZ0Lz1B3rDpv4sXBrmgxVhlsTPdK1aF+W31+3BgH7b/kgqKTEO2qec5rCz125l7N2/dMufu/QK\nbdlu4vjRW/IgNu3UVD+NP959ObW1exKJJm9pWb0uQo/uxsZNzsIPwyz8MHZ2ZNCA5MXYmvURHnlu\nPda8lF9Mu4Nen7i43fHV1tZs2X5efRMPPrmODY1R1seLqw2NUY48sBvXnr9ru/0vWh5mxmNrt1m3\nam0LfTo4k7NyTYTX321qt58NjdGkxdhbC5v56YyGdus/O6Q7k8bExjN5yozYWbh4ZqiskoqacZz4\nrWnUHHkJAF84spKrv1fdbj9z3tjE5HtXtlvf0fbz6pqYdMPdDBxyyTZ5fQ+4hMlTZrSbNtxnzzJO\nOqpym+KquqqUAf1C7fYNsO9e5ey7V/k26666LPl/KxOnX550H9minjEREelSo8ZcRZ1/N2lfTmjv\nC1mwuHmb7cvLjCnjduOT+1bscObOTK2tb4yyrKGFDxtaWN7QQkW5cdrQ9sXY6+9u5tKfr6Bu7tS0\n+o7mvr2JCXd83G4/n9q/glsv7t9u/eKPwjzxfxvo2b2EnpUl9Kos4fap17Oy+8ikWTffOIm6D8M0\nNztN4fijOcqAfqUcdVD3dvv/73ub+f3f12/ZtrnZ2Rx2jj6oGz84oy8Ap31nAmv7jG333rqXb6P2\n6B9RUgJDD09eXL305iZ++cfVlIaMUAmEQkZpCI44oBujTqlqt/28uiZGnHclfQ64pN1rfdbeycMP\n3NRufVfIVQ+eesZERCRjPl7dwn/fa+K/7zXxxntNPPfKRmqPTn4256xTKzl4n/JtznTt1jfUbopy\ne9XW1uxwA3avyhJ6DSxn8MDylNv16xPiOyf35o55pNV3tN/e5VwzuppelVuLq16VJVR2S36sA/uX\nMea0vtusq7nugq09Y2WV25zJ6dsrRN/9k58VSubQ/bpx6H7dUm6TOOXbKhJu5AtH9eSuO/ZO+fd0\nzCe7c8wn2xeBHTmwtoLDD6xkQZK8TE4b1tbu+H8rmaJLW6QpqNdbUV5hZylPebnOm/rgKr511Yf8\n7J6VPP7PDdQvC1NSUkIk3AjA6qVzgK0/YId/qTcXnbULpw3txZEHdmdAv9KdLsQSZfLz3Gu3Ms47\ntYojD6rs8PgS9e0V4nOHV3L4Ad0YPLCc3atL6VlZsl3HW1tbw4PTL2dw+UyaF0xgcPnMjDbvTxw/\nmqb6aUTCjaxeOmdL8Xf15aO79O+ps7yJ40d3eVZbujeliIgUhEjUee+DZhYubU76+sABZfToZhx9\ncDdGf70Pv/jRbvx15kVbfsACWf0Bmw2JBQRk/vhqa2Nncq6/+gLuuvP6jE6p1dZuLf56bHwk48Vf\ntvPylXrGRERki3CL886iZv773mbeeK+JNxc2sXGTd9iE3Rx2QiHafVsx6NfGCvrxSddL1TOmYkxE\npAikWzz8661NXHnntk3n/XcJccKnKrc0eYvI9surG4Wb2TAzm29mC8xsQpLX9zazZ8zsFTN7zcy+\nnO0xJlPofR3Ky15ekI9NeYWZl3i7oPoNh7OgeQRfG3Fj0lvAHLxPBbV7lPG143ty1bn9mHX9Hjx4\n/Z47XIgF8fPMVV6Qj60Y8lLJ6rcpzawEuAM4EfgQmGtmj7r7/ITNrgZ+5+6/MrMDgb8Ctdkcp4hI\nkCS7dlS/gy7hupvu4tf/+7Nttu3ZvYS7r949F8MUKVpZnaY0s2OAa9z9y/HlKwB395sStvklsNDd\nbzGzY4Fb3P34JPvSNKWISBo6unZUz1V38tiszFzLSUS2lU/XGdsT+CBheQlwdJttJgFPmdk4oBI4\nKUtjExEJpIqyEJFw+2s59e+X21vAiEhMtnvGklWEbU9vDQfucfe9ga8CMzM+qjQEfS5beYWZpTzl\npeOaK0fz8ZtTi+JaTkHOC/KxFUNeKtk+M7YEGJiwvBex3rFE5wEnA7j7S2bWzcyq3b3dDbVGjRpF\nTU0NAFVVVQwZMmTLDXBbP+SuWn7ttde6dH/KC3aelrWcT8sfLVvMj8cN5Zl/zmTexvfp+fGf+f73\nvrrl25S5Hp+W01tupbzCyGt9Xl9fT2ey3TMWAt4h1sC/DHgZGO7u8xK2+QvwkLvfF2/gf9rd90qy\nL/WMiYiISEHIm0tbuHsEuBB4CngLmOXu88xskpmdEt9sPHC+mb0GPACMzOYYRURERLIpq8UYgLs/\n4e77u/sn3P3G+Lpr3P3P8efz3P14dx/i7oe7+z+yPcZk2p7WVJ7y8iFLecpTXvHkBfnYiiEvlawX\nYyIiklkbNkW59Ocf8co7m3M9FBFJg26HJCISMFMfXMVj/9zAQbXl3D6+P2ZJ21REJIvypmdMREQy\n662FTTz+wgZCJfCjb++iQkykAKgYS1PQ57KVV5hZylNeopaIc9tvV+EOZ53Um332LM9oXjqUV5hZ\nyssuFWMiIgHx0NPrqPswzO7VpZzzld65Ho6IpEk9YyIiAfHi641MnbWaCefswpEHds/1cEQkQaqe\nMRVjIiIB0tQcpaJckx4i+UYN/F0g6HPZyivMLOUpr63OCrFCP75izgvysRVDXioqxkRERERySNOU\nIiIiIhmmaUoRkQB6fcFmfvO3tYRb9IupSCFTMZamoM9lK68ws5RXvHnNYefW367insfX8vg/N2Q8\nb0cprzCzlJddKsZERArQb59cy5IVLQzsX8opx/fM9XBEZCeoZ0xEpMAsXh7m/MnLCLfA1B/txqH7\ndcv1kESkE+oZExEJiGg0dsujcAt85bgeKsREAkDFWJqCPpetvMLMUl7x5TU2OeVlRt9eJVxwWt+M\n5+0s5RVmlvKyqzTXAxARkfT17F7CTRfuyorVEXpV6vdpkSBQz5iIiIhIhqlnTERERCRPqRhLU9Dn\nspVXmFnKU57yiicvyMdWDHmpqBgTEclzT720geUrW3I9DBHJEPWMiYjksfeXNHPBjcvpVm488NM9\n6NMzlOshicgOUM+YiEgBikRjtzyKRuGLn+6hQkwkoFSMpSnoc9nKK8ws5QU777HnNzC/vpl+fUKM\n/npVxvMyQXmFmaW87FIxJiKShz5e08Ldj60B4KKz+tKju/65FgmqrPeMmdkwYCqxQvBud7+pzeu3\nAZ8HHOgB7OruuyTZj3rGRCSwZr/SyA33NnDUQd257oJqzJK2mohIgUjVM5bVYszMSoAFwInAh8Bc\n4Gx3n9/B9hcCQ9x9dJLXVIyJSKAtXh6me4Wxa1/dLEWk0OVTA//RwLvuvsjdw8As4NQU2w8HHszK\nyDoR9Lls5RVmlvKCnTdwQFmXF2L5dHzKy98s5WVXtouxPYEPEpaXxNe1Y2YDgRrgmcwPS0RERCQ3\nsj1NeSbwJXcfE18eARzl7hcn2fZyYM9kr8Vf95EjR1JTUwNAVVUVQ4YMYejQocDWilfLWtaylrWs\nZS1rOdvLrc/r6+sBuO+++/KmZ+wY4Fp3HxZfvgLwtk388ddeAX7o7i91sC/1jIlIYEQizqsLNnPk\ngd1zPRQRyYB86hmbC+xnZoPMrBw4G3is7UZmtj9Q1VEhlguJla7ylJcvWcoLTt4fnlnP5bd/zB0P\nrcpKXrYorzCzlJddWS3G3D0CXAg8BbwFzHL3eWY2ycxOSdj0bGLN/SIigbd8ZQv3/WUtAEcdrDNj\nIsVG96YUEckhd2fi//uYf721mc8fUcmPz6vO9ZBEJANSTVPq4jUiIjlQV1fP5CkzeHfxZhYtj7LP\nYWcy9sxP53pYIpID2e4ZK1hBn8tWXmFmKa8w8+rq6hk+5mYWNI9gbclRDBwyho/n38/aVR90/uad\nFMTPs1jygnxsxZCXiooxEZEsmzxlBhU14wiVVQIQKquk74GXMHnKjByPTERyQT1jIiJZdtp3JrC2\nz9h26/usvZOHH2h3pR8RCYB8urSFiEjRq64qIxJu3GZdJNxIdVVZjkYkIrmkYixNQZ/LVl5hZimv\nMPMmjh9NU/00IuFGVi+dQyTcSFP9NCaOH53x7CB+nsWSF+RjK4a8VFSMiYhk0evvbmbA7gN5cPrl\nDC6fSY+NjzC4fCYPTr+c2tqaHI9ORHJBPWMiIlmyZEWYMTcsZ5feIe68rD99eoZyPSQRyRL1jImI\n5FhLxJl870o2NzkHDCpXISYiW6gYS1PQ57KVV5hZyiucvN/8dS3z65vZrW+IS87eJeN5HVFe4eYF\n+diKIS8VFWMiIhn25vtNPPDEOszgypH96Fmpf3pFZCv1jImIZNivH1/DzL+t4+wv9WbMN6pyPRwR\nyYFUPWMqxkREsuBfb23i8P27UVaa9N9iEQk4NfB3gaDPZSuvMLOUVzh5nz64e9JCLCjHp7xgZSkv\nu9IqxszsgEwPRERERKQYpTVNaWZRYA4wA3jI3TdmemCd0TSliIiIFIqumKY8FHgZuAlYZmYzzOzY\nrhqgiEiQPPWvjbz3QXOuhyEiBSKtYszd33T3S4E9gHOBAcDzZva2mf2Pme2WyUHmg6DPZSuvMLOU\nl3957y9p5tYHVjL2luUsX9mS8bztpbzCzQvysRVDXirb1cDv7i3u/kfgNGA8sA9wC7DYzO41s/4Z\nGKOISEFoao5y/T0rCbfAsGN7MqBfaa6HJCIFYLsubWFmhwLfA74DhIH7gbuJnTG7Fuju7sd0/TCT\njkU9YyKSV25/aBUPz97A3v1L+dWVA+hWri+si0hMqp6xtH5tM7MfEivCDgOeBi4AHnP31nPw75rZ\nOUBdF4xXRKTgvPzWJh6evYFQCVx1brUKMRFJW7r/WlwB/BnYx92/4u5/SijEWq0Axnbp6PJI0Oey\nlVeYWcrLn7xNTU5lN+Pcr/Vh8MDyjOftKOUVbl6Qj60Y8lJJt6FhUGdzgu7eBPxq54ckIlJ4Pnd4\nJQfWlNOvKpTroYhIgUn3OmNjgPXu/mCb9cOBnu5+V4bGl2pM6hkTERGRgtAV1xkbDyxPsn5p/LXt\nGcwwM5tvZgvMbEIH25xlZm+Z2RtmNnN79i8iIiJSSNItxgaSvDl/cfy1tJhZCXAHcDJwMDC87a2W\nzGw/YAJwrLsfAlyS7v4zKehz2corzCzlKU95xZMX5GMrhrxU0i3GVgCHJFl/GLByO/KOBt5190Xu\nHgZmAae22eZ84E53Xwfg7g3bsX8RkayY+be1PPrcetQuISI7K92esZuBbwLnAC/EV38WuA/4k7v/\nT1phZmcAJ7v7mPjyCOBodx+XsM3DwALgOGLF4iR3fzLJvtQzJiI58cZ7m7n05ytwYPqVA9h3r/S/\nPSkixWmnrzMG/Bj4BPAc0HrDtTLgcWDi9owlybq2FVUpsB9wArEp0H+a2cGtZ8pERHJpw6YoN9y3\nkqjD8C/1ViEmIjstrWIsftmK08zsEGAIsaLqFXd/czvzlrBtj9lewIdJtpnj7lGg3szeIVYI/qft\nzkaNGkVNTQ0AVVVVDBkyhKFDhwJb54K7annq1KkZ3b/ygpOX2IegvODl3f67Vcz77wvstVspo045\nPXDHp7z8zWubqbz8zmt9Xl9fT6fcPWsPIAS8BwwCyoHXgAPbbHMycG/8eTWwCOibZF+eTc8++6zy\nlJd3WcrLbt4zczf453+wyIeNW+yLljVnPC8TlFe4eUE+tmLIi9ctSeujtO9NaWY1wOnEzmyVtyno\nfpjWTmL7GQb8glg/2N3ufqOZTQLmuvuf49vcCgwDWoDr3f33Sfbj6Y5dRKQrLF4e5mf3NPCV43py\n6gm9cj2gL30gAAAgAElEQVQcESkgqXrG0m3g/yLwGDCf2CUpXgf2IXam62V3/1LXDTc9KsZEJBda\nIk6oJPYPq4hIurrioq+TgRvd/VNAE/AtYmfIniNWpAVe4hyw8pSXL1nKy35eaci6tBDLt+NTXv7m\nBfnYiiEvlXSLsQOA1ivhtwDd3X0j8BPgskwMTERERKQYpDtNuRz4vLvPM7O3gSvc/TEzOxT4P3fv\nmemBJhmTpilFJKMiEadEU5Ii0gW64jpjLwOfAeYBTwC3mNmBwBnx10REAueOP6xmzfoolw7vS+8e\noVwPR0QCKt1pysuIXYYC4Brg/4DziN0m6bwMjCvvBH0uW3mFmaW8zOW99OYmHn1uAy++3sjylZGM\n52WL8go3L8jHVgx5qXR6ZszMSoE9gVcB3H09cG6GxyUikjOr10e4ZWbstrvnfq2KwQPLO3mHiMiO\nS7dnbDOxi7PWZX5I6VHPmIhkgrtz9f82MOeNTRz2iQqmXLwboRL1jInIzumKnrE3gVogb4oxEZGu\nVFdXz+QpM3h38WYWLY9Se9iZXDHyaBViIpJx6faMTSTWtD/MzHY1s8rERyYHmC+CPpetvMLMUl7X\nqKurZ/iYm1nQPIK1JUcxcMgYVr5zP41rl2Q8O4ifp/IKP0t52ZVuMfYE8Cngr8ByYH2bh4hIwZo8\nZQYVNeMIlcV+twyVVVJ1wCVMnjIjxyMTkWKQbs/Yyaled/cnu2xEaVLPmIh0ldO+M4G1fca2W99n\n7Z08/MBNORiRiATNTveM5aLYEhHJluqqMlY1N245MwYQCTdSXVWWw1GJSLFIa5rSzA5K9cj0IPNB\n0OeylVeYWcrbOe7OH59Zx4XfP5em+mlEwo2sXjqHSLiRpvppTBw/OmPZrYL0eSovOFnKy67t+Tal\nA62n19rOD+rS1CJScGY9vZ67HllD7R6VzPzlZdz087uZt/F9Bpe/wcTpl1NbW5PjEYpIMUi3Z2z/\nNqvKiDX0TwCudPfHMzC2zsaknjER2WF/m7OBW36zCjP48ff6MfSIHrkekogEWFf0jL2TZPWbZtYA\nXAlkvRgTEdlRc97YxK0PrAJg7Jl9VYiJSE6le2mLjrwLHNEVA8l3QZ/LVl5hZilv+y3+KMxPZzQQ\njcJ3Tu7N6Z/vldG8zihPefmYpbzsSuvMWJILuxqwO/BT4L2uHpSISKbstWspXz+hJxsao3zv631y\nPRwRkbR7xqK0b9oH+Aj4lrv/s6sH1hn1jInIzohGnRLd6khEsqQr7k35FbYtxqLAx8Db7t68k+MT\nEck6FWIiki/S6hlz9yfc/cmEx9Pu/loxFWJBn8tWXmFmKU95yiuevCAfWzHkpZLuRV/HmNnwJOuH\nm9n5XT8sEZGdF4k4/+8Pq/l4TUuuhyIi0qF0e8YWABe4+7Nt1p8A3OXuba9DlnHqGRORVNydKTNX\n8bc5G9lv7zJ+dcUAzDQ1KSK5kapnLN1LWwwE6pKsXxx/TUQkr/z6sbX8bc5GKsqMi7+1iwoxEclb\n6RZjK4BDkqw/DFjZdcPJX0Gfy1ZeYWYpL7k/PbueB55cR0kJXDO6moP3qcho3s5QnvLyMUt52ZVu\nMTYLmGZmn7WtTgCmAr/bnkAzG2Zm881sgZlNSPL6SDNbYWavxB/f2579i0hxm1/fxJ1/WA3A5SN2\n4ZhDuud4RCIiqaXbM1ZBrCA7FWj9BmUZsdsgfcvdm9IKMysBFgAnAh8Cc4Gz3X1+wjYjgSPcfVwn\n+1LPmIi04+785m/rKC81zv5S71wPR0QE6Jp7UzYBp5nZJ4ndINyAV9z9ze0cy9HAu+6+KD6w1gJv\nfpvt1NwhIjvEzDjnK7qyvogUjnQvbVFiZiF3f9Pdf+Pu97v7m2YWip/tSteewAcJy0vi69o63cxe\nM7OHzGyv7dh/xgR9Llt5hZmlPOUpr3jygnxsxZCXSrpX4P8DMAe4pc36S4DPAGekuZ9kZ7zazjU+\nBvzW3cNmdgFwH7FpzXZGjRpFTU0NAFVVVQwZMoShQ4cCWz/krlp+7bXXunR/ygt2npa1rGUtd/Vy\nK+UVRl7r8/r6ejqTbs/Yx8AX3P2NNus/CfzD3ft3upPY9scA17r7sPjyFYC7+00dbF8CrHL3qiSv\nqWdMpMht3BTllpkrGXNaX/aoTvd3SxGR7OuK64z1ZGvjfqIWYHs6ZOcC+5nZIDMrB84mdiYscbAD\nEhZPBd7ejv2LSJFoDjs//tXHPP/qJm6+fyX65UxEClW6xdibwFlJ1p/FdhRL7h4BLgSeAt4CZrn7\nPDObZGanxDcbZ2Zvmtmr8W1Hpbv/TGp7WlN5ysuHrGLNi0Sdyfc28NqCJvr1CXHFyH5ddlHXfDg+\n5Skv11nKy650z+tfD/zBzGqAZ+LrTgRGAN/ankB3fwLYv826axKeTwQmbs8+RaR4uDt3/H41z7+6\niR7djBvH7sqAfpqiFJHClVbPGICZfQO4mthV9wFeB37m7g9naGydjUc9YyJF6JV3NjP+FysoK4Wb\nL9yNwwZ3y/WQREQ6lapnLO1iLN+oGBMpXn94Zh279S3lhE9V5nooIiJp6YoG/qIX9Lls5RVmVrHm\nnfmF3hkrxPLh+JSnvFxnKS+70irGzKzUzK40s/+a2Roza0x8ZHqQIiIiIkGV7nXGrif2rcZbgBuB\nnwK1wOnErht2RwbH2NGYNE0pEmB1dfVMnjKDhtVhqvuWMXH8aGpra3I8KhGRHbPTPWNmthC4yN3/\nYmbrgSHu/r6ZjQM+4+5nd+2QO6diTCS46urqGT7mZipqxhEqqyQSbqSpfhoPTr9cBZmIFKSu6Bkb\nALRefX8D0HoX3j8DX9654RWGoM9lK68ws4KaN3nKjC2F2OqlcwiVVVJRM47JU2ZkPDuIn6fygpEX\n5GMrhrxU0i3GlhAryAAWsvVekUcATV09KBEpXqvWRZj7diOhsm0b9ENllTSsCedoVCIimZPuNOWt\nwBp3v87MhgP3A+8R6xu73d0vy+wwk45J05QiAROJOCN/uowX/zqFgUPGbFOQRcKNDC6fyV13Xp/D\nEYqI7Jguv86YmX0OOA5Y4O5/2Mnx7RAVYyLB9Lf/28DDT87n1X/+msp91TMmIsHQ5dcZc/fn3H1y\nrgqxXAj6XLbyCjMriHnDju3Br649gofuvpzB5TNpXjCBweUzs1aIBe3zVF5w8oJ8bMWQl4pu6CYi\nObFiVQvVVSFKSrb9RbH1ht+1tTXcdef1zJ49m6FDh2Z9fCIi2aLbIYlIVkWiziOz13P3Y2u54PQq\nTj2hV66HJCKScammKXVmTESyZvHyMDf/ZiVv1zUD8N4HzTkekYhI7unelGkK+ly28gozq1DyIhHn\nt0+u5fzJy3i7rpl+fUJc9/1q/uc7/TKStzOUp7x8zQvysRVDXirp3pvyr2bWJ8n6Xmb2164flogE\nisELr28i3AJf+UwP7vnx7hx3aGZu9C0iUmjSvc5YBNjd3Ve0Wb8r8KG7l2VofKnGpJ4xkQJSvyxM\nw5oWjjywe66HIiKSdTvcM2ZmB7U+BQabWXXCyyFgGPBhl4xSRAKtZvcyanbP+u9tIiJ5r7NpyjeJ\n3ZPSgefiz1sfrwPXATdkcoD5Iuhz2corzKx8y9vcHOXux9awZn0kK3mZoDzl5WtekI+tGPJS6ezb\nlAcSOyv2NvBZoCHhtWZgmbtvztDYRKSAvL5gM1MeWMXSj1tYvrKFq86t7vxNIiKSds9Yhbvn1Q3B\n1TMmkh82bopy1yNreOyfGwCo3aOMy0bswgE1FTkemYhI/uiK64x92czWufsz8R1eDowB3gJGu/vH\nXTNUESkkm5qinD95GctXRgiVwIgv9+HbJ/emrDTpvzciIpJEutcZux4oBzCzw4j1it0P7ALcmpmh\n5Zegz2UrrzCzsplXV1fP+WOv5viThnP+2Kupq6une0UJxx1Wyf4Dy/nVlQMY+dU+XV6IBfXzVJ7y\n8jlLedmV7pmxGmB+/PnpwKPu/lMz+zOg64yJBFxdXT3Dx9xMRc04NvZ4nQXNhzF8zM08OP1yzj91\nEKESCIV0NkxEZEek2zO2Cjje3d82sxeA+919upnVAG+7e9pXbzSzYcBUYmfl7nb3mzrY7kzgIeBI\nd38lyevqGRPJknO/fxULI98lVLb1f/VIuJHB5TO5687rczgyEZHC0BU9Yy8CN5nZ88DRwNnx9Z8A\nlm7HQEqAO4ATiV2fbK6ZPeru89ts1xO4CHgp3X2LSNeKRp1XFzTx5EsbeP6VjQw6ctvfuUJllTSs\nCedodCIiwZFuz9hFQDdgNHCxuy+Jr/868I/tyDsaeNfdF7l7GJgFnJpku+uAm4C8+QZn0OeylVeY\nWZnK+8uLG/j2jz/ksmkr+PvLjUS9hEi4EYDVS+cAsTNj1VWZv4hrED5P5Smv0LKUl11pFWPuXu/u\nX3T3/d39lwnrL3L3729H3p7ABwnLS+LrtjCzIcBe7q5eNJEcaYk4K1ZHGNAvxDlf6c2D//tDmuqn\nbSnIIuFGmuqnMXH86ByPVESk8KXVMwZgZmXAycC+wD3uvs7M9gbWuvu6NPdxJvAldx8TXx4BHOXu\nF8eXDXgGGOnui83sWWC8u/8nyb7UMyayEyIRZ+nHLQwc0P7s1vrGKAuXNHPIfhWUlMRaHOrq6pk8\nZQYNa8JUV5UxcfxoamtrsjpmEZFCtdM9Y/FG/aeB/kAl8DiwDvgfoDtwQZpjWQIMTFjei23vbdkL\nOBiYHS/MBgCPmtnXkzXxjxo1ipqaGgCqqqoYMmQIQ4cOBbaeftSylrW87fLCpc3cPuNJXnlnM/32\nOpaHbtiTF/753Dbb/+fl5wEoGbzt+1ub9WfPns2iRfVbirF8Oj4ta1nLWs6H5dbn9fX1dMrdO30A\njwL3AmXAemCf+PrPAe+ls4/49iHgPWAQseuWvQYcmGL7Z4FPdfCaZ9Ozzz6rPOXlXdb25D08e52P\nmfyhf/4Hi7Y8vnvNUl/yUXNG8rqK8pSnvOxnKa/rxeuWpPVOut+mPA44zt3DsRNWWywC9khzH7h7\nxMwuBJ5i66Ut5pnZJGCuu/+57VuI3RtTRHbSi69v4t0PwvTobnzhyB6cfEwPDqwpp83/0yIikmXp\nXmdsNbFi7G0zWw8c5u4Lzex44I/u3j/TA00yJk9n7CJBlayHq6ZmEM1hp6K8pN32r76zmbUbInzm\n0ErKy1SAiYhkU6qesXSLsYeAle7+g3gxdiiwAngE+NDdR3blgNOhYkyKWeIV8UNllUTCjax8eyoH\nHfM9jjhsXyac0y/XQxQRkQSpirH2vz4nNx442cz+S+x6Y/cDC4FaYEKXjDLPJTbkKU95uc6aPGXG\nlkJs9dI5hMoq6XfQJcx9fhavv7uZSDRzv6gE+e9OecrL57wgH1sx5KWSVs+Yxy4zcSjwXeAIYkXc\n74D73H19BscnIkk0rAkT6tP+ivi1u4e475o9CJVoGlJEpFCknKY0s18Tu+J+3hVcmqaUYnb+2KtZ\n0DxC94oUESkQOzNNOZLYdcREJI9MHD9aV8QXEQmIzooxzXXEBX0uW3mFlVVbW8OD0y9ncPlMmhdM\nYHD5TB6cfnlWrogf5L875Skvn/OCfGzFkJdKOj1jmgsUyUO1tTXcdef1zJ49e8uVn0VEpPB01jMW\nJY1izN1DXTmodKhnTIrJ5uYoN9+/ipFf7cOg3dvfS1JERPLbzt6bcgywpmuHJCLpCrc410xvYO7b\nm1nycZhfXTFAV80XEQmQdK4z9ri7/zHVI+OjzANBn8tWXn5mRSLOz+6JFWJVPUu4+tzqdoVYkD9L\n5SlPebnJUl52dVaMaR5QJEeiUefW367i+Vc30aO7cdNFuzFwgKYoRUSCJp2esQHuviJ7Q0qPesYk\n6F6Zv5nx01bQrdy4+aLd+OS+FbkekoiI7KCdvjdlPlIxJsXg8X+uZ0C/Uo46SJf7ExEpZF1xb8qi\nF/S5bOXlZ9bXPtur00IsyJ+l8pSnvNxkKS+7VIyJiIiI5JCmKUXyRFNzlIpy/X4kIhJEmqYUyXMv\nvbGJEdcs470PmnM9FBERyTIVY2kK+ly28nKX9dqCzVw7o4GVayO88HpjxvN2lvKUp7zc5AX52Ioh\nLxUVYyI5NK++iat++THNYedrn+3JyK/2yfWQREQky9QzJpIjdR82c8ltK1jfGOXEoyq5cmQ/Skp0\nmyMRkSBSz5hIHnpnUTMbNkX5zKHdmXCOCjERkWKlYixNQZ/LVl72s4Yd25Mbx+7KT86rpjS044VY\nkD9L5SlPebnJUl52leZ6ACLFTFfWFxER9YyJiIiIZJh6xkRybFNTlPpl4VwPQ0RE8lDWizEzG2Zm\n881sgZlNSPL6BWb2XzN71cyeN7MDsj3GZII+l628zGU1h51rpjdw0ZTlvF3XlPG8TFOe8pSXm7wg\nH1sx5KWS1WLMzEqAO4CTgYOB4UmKrQfc/VB3/xRwC/DzbI5RpCtFIs7P7mng3/M2UxYyelbqZLSI\niGwrqz1jZnYMcI27fzm+fAXg7n5TB9sPB0a4+1eTvKaeMclr0ahzy8xVPPnSRnp0N35+SX/227s8\n18MSEZEcSNUzlu1vU+4JfJCwvAQ4uu1GZvZD4EdAGfCF7AxNpGv98k9rePKljXQrN2744W4qxERE\nJKlsF2PJKsJ2p7fc/f8B/8/MzgZ+DIxKtrNRo0ZRU1MDQFVVFUOGDGHo0KHA1rngrlqeOnVqRvev\nvMLPW7ZsOc+88Cbz3nmfPj1LOfTwL9Ct/CSu+/6uNHwwh9kfZOb4EvsesvF5Kk95ystNXttM5eV3\nXuvz+vp6OuXuWXsAxwBPJCxfAUxIsb0Bazp4zbPp2WefVZ7yOrRwYZ1/+qQf+Amj5/mQr8/yE0bP\n80+f9AN/9b/vZTTXPXifpfKUp7zcZymv68XrlqT1TrZ7xkLAO8CJwDLgZWC4u89L2GY/d38v/vxr\nwI/dPdlUpmdz7CKpnD/2ahY0jyBUVrllXSTcyODymdx15/U5HJmIiOSDvOkZc/eImV0IPEXsm5x3\nu/s8M5sEzHX3PwMXmtlJQDOwGhiZzTGK7IiGNWFCfSq3WRcqq6Rhja4tJiIiqZVkO9Ddn3D3/d39\nE+5+Y3zdNfFCDHe/xN0/6e6Hu/uJiWfNcilxDlh5ymurV2UpkXAjAKuXzgFiZ8aqq8oymgvB+yyV\npzzl5T5LedmV9WJMJGiamqO09P0G9XNv21KQRcKNNNVPY+L40TkenYiI5Dvdm1JkJ7g7P7tnJc/8\nu5FeoWX0bXqMtRtbqK4qY+L40dTW1uR4hCIikg/ypmdMJGhmPb2eZ/7dSPcKY+pln6J2j0/nekgi\nIlJgNE2ZpqDPZStv+730xiZmPLoGgImj+lG7R3nGslJRnvKUVxx5QT62YshLRWfGRHbQ5rBTXmp8\ne1hvjjussvM3iIiIJKGeMZGdsHRFmD12LcUsaRuAiIgIkLpnTMWYiIiISIalKsbUM5amoM9lK68w\ns5SnPOUVT16Qj60Y8lJRMSaSpg2N0VwPQUREAkjTlCJpmFfXxOV3rOCib/blS8f0zPVwRESkwGia\nUmQnNKxp4SfTG9i4yXm7rjnXwxERkYBRMZamoM9lKy+55rDzk+kNrFwb4bBPVHDhWX0zlrWjlKc8\n5RVHXpCPrRjyUlExJtIBd+fWB1Yyv76Z/ruEuGZ0NaUhXcJCRES6lnrGRDqwdEWYMTcsx4Hb/6c/\n++5VnushiYhIgdJ1xkR2UN2HzXy0KsIxn+ye66GIiEgBUwN/Fwj6XLbykqvdo3y7C7FCOTblKU95\nhZUX5GMrhrxUVIyJiIiI5JCmKUVEREQyTNOUImm4+9E1PPb8+lwPQ0REioyKsTQFfS672POe/tdG\nHnhyHbc/tJrFH4UzmtXVlKc85RVHXpCPrRjyUlExJkVvfn0TUx5YCcCF3+zLwP5lOR6RiIgUE/WM\nSVFbuTbC929czsq1EU45vieXDu+LmS7sKiIiXUs9YyIduGXmSlaujXDIfhVcdJYKMRERyT4VY2kK\n+lx2seZd+M2+HHVQN649v5qy0q4pxPLl2JSnPOUFKy/Ix1YMealkvRgzs2FmNt/MFpjZhCSvX2pm\nb5nZa2b2tJntne0xSvHYa7cybrpwN/r2CuV6KCIiUqSy2jNmZiXAAuBE4ENgLnC2u89P2OZzwL/c\nfbOZfR8Y6u5nJ9mXesZERESkIORTz9jRwLvuvsjdw8As4NTEDdz9OXffHF98Cdgzy2MUERERyZps\nF2N7Ah8kLC8hdbF1HvC3jI4oTUGfyy6GvI2bovzlxQ1k+oxqMXyWylOe8rKfF+RjK4a8VEqznJfs\n9FzSn4xmNgI4AvhcRkckRSESdX52TwMvvbmZj1e3MOqUqlwPSUREBMh+z9gxwLXuPiy+fAXg7n5T\nm+1OAn4BnODuKzvYl48cOZKamhoAqqqqGDJkCEOHDgW2VrxaLu7lQYNqmDxlBi/8awGr1zuHfO5H\n3PuzI3n3rRfzYnxa1rKWtazlYC63Pq+vrwfgvvvu67BnLNvFWAh4h1gD/zLgZWC4u89L2OZTwO+B\nk939/RT7UgO/pFRXV8/wMTdTUTOOUFklkXAj6xb8gj/dO4Ha2pocj05ERIpJ3jTwu3sEuBB4CngL\nmOXu88xskpmdEt/sZqAH8Hsze9XMHsnmGDuSWOkqrzDyJk+ZsaUQW710DqGySnoPvpjJU2ZkNDeI\nn6XylKe83OcF+diKIS+VbPeM4e5PAPu3WXdNwvMvZntMEkwNa8KE+lRusy5UVknDmp27EbiIiEhX\n0r0pJbDOH3s1C5pHECrbWpBFwo0MLp/JXXden8ORiYhIscmbaUqRTHF3Vq6NbLNu4vjRNNVPIxJu\nBGKFWFP9NCaOH52LIYqIiCSlYixNQZ/LLuS8RcvCjJ+2ggtvWc7m5uiW9bW1NTw4/XIGl8+kecEE\nBpfP5MHpl2e8eb+QP0vlKU95+ZsX5GMrhrxUst4zJtJVNm2O8pu/reX3/1hPJAq9e5RQ/2GYA2oq\ntmxTW1vDXXdez+zZs7d87VhERCSfqGdMCtJLb27itt+uomFNBDP46nE9Oe/rfejTUzf8FhGR/JOq\nZ0xnxqQwOTSsibD/oHIu/lbfbc6GiYiIFBL1jKUp6HPZhZZ3zCHduWHsrtx5Wf+0CjH1dShPecor\n9LwgH1sx5KWiM2OS19ydaBRCofZndj99cPccjEhERKRrqWdM8taiZWGmPbSKg2orOO/rurG3iIgU\nLvWMSUFp+y3JxctbGDGsNxXlmlUXEZHg0U+3NAV9Ljtf8mb/ZyMjf7qMWU+vJ+rwteN7MuOqATtd\niKmvQ3nKU16h5wX52IohLxWdGZO88o9/N8a+JTmwnIvP1rckRUQk+NQzJnll+coW/j1vM1/+TA9C\nJUmn1kVERApOqp4xFWOSVXV19UyeMoOGNWGqq8qYOH50xm9PJCIikmu6UXgXCPpcdjby6urqGT7m\nZhY0j6B+w+EsaB7B8DE3U1dXn/Fs9XUoT3nKK/S8IB9bMeSlomJMMm5+fRM//+0qzjjvDipqxhEq\nqwQgVFZJRc04Jk+ZkeMRioiI5I6mKWWnbG6OsuSjFhZ/FKa81Dh+SGW7bV54rZGfTG+g7uXbqD36\nR+1e77P2Th5+4KZsDFdERCQndJ2xApLtnqodyav7sJn//dMaFi8P89GqyJb1B9WWJy3GDqgpZ+yZ\nVTywrjsrw41bzowBRMKNVFeVddHRiIiIFB5NU3airq6e88dezfEnDef8sVdntL+po56qhQvryMRZ\nwGR53/zeTfzuL/P47RNrue8va5O+r6zUmPv2Zj5aFSFUAoMGlHL8Yd059pDktyeqrirljC/05tbr\nLqCpfhqRcCOrl84hEm6kqX4aE8eP7vJja0t9HcpTnvIKPS/Ix1YMeanozFgKrcVKRc04NvZ4nQXN\nhzF8zM08OP3ybc4eRaPOG+81sanZaWp2NjdH2dzkNLc43zyxd7v9NoedCXesYHOzxx5NUZqanTf/\nOY3dP5msp+puFjKGEoOSEigpMUpKIFQCj9+6d7v9R6POyEnLtmwbir8vVGL88ooBW7abPGVGux6u\nHvtdzBXXTqf2qEvo0d045yu9Mdv2rOru/Uq57vvVDOxfxu7VpZQmuW9kMrW1NTw4/XImT5nBvI3v\nM7j8DSa2+SxFRESKTUH3jI3+4VXbPY0XjTqNm531jVE2boqy397l7baJRJyf3bOSRx+8kZ77jG43\nrTa4fCZ33Xn91nVR54sXfpA07+937E1Jm+tlRaPOSUm276inqveaO1lXNbbd+pIS+PsdA9utb4k4\nX7qo/f7bbn/adyawtk/7/a58ayoXXPRjBg4o48vH9kh6k24RERFJX2B7xhY0j+DMc2/ix1ddTJ++\ne7O+Mcopx/dsV/y4O+dcu4y1GyJs3Owk1p9P3b53uzM7JSXw4n8bWbW2hT5l2/ZAhcoqaVgT3nZd\niXH4/hWUhoyKcqNbudGtooRu5UbU288Fl5QYt12yGxVlRrcKo1t5CRXlxvjLe/B+kp6qXfuW8fAd\nexONQiQKUXeiUYhGk38uoRK475rdY9vEt41EaTfVWV1Vxqrm9nlHf7KSH57ZN/nORUREpEsVdM9Y\nqKySnp+4mEsnTue6X69k6qzVNDa1P9NnZqzdEGHDplgh1qOb0X+XEPvtVcbm5uTbX3VuNUP2704k\n3AjA6qVzgI4bzqdc3J8bL9yNSWN25cpR1Vw6fBd+cEbfDqfwhgzuxoG1FdTuUc7u1aXs0jvEjyec\n32FPlZkRChnlZbHirbJbCT0rk//1mRl79y9j0O5l1O5Rzr57lTN4YDn7D9r21kITx48uih6ubOcF\n+diUpzzl5S4vyMdWDHmpFPSZMYgXZN2dEz7VPVacdDDrOn3i7nSvMHp2L0lr2u2ET1Wy9/UXbOkZ\nA7YWK9Mv78pD2KK2Nrs9VdnOExERkfYKumfs8z9YlLSHqyvp9j0iIiKys/Lq3pRmNgyYSmyK9G53\nvzoZ19cAAA+PSURBVKnN65+Nv34o8C13/1MH+/ETRs+jqX5au283ioiIiOSTvLk3pZmVAHcAJwMH\nA8PN7IA2my0CRgIPdLa/weUzs1aIBX0uW3mFmaU85SmvePKCfGzFkJdKtnvGjgbedfdFAGY2CzgV\nmN+6gbsvjr/W6Sm7TE1NioiIiGRLVqcpzewM4GR3HxNfHgEc7e7jkmx7D/B4qmnKQu13ExERkeKS\nT9cZSzaIHa6oRo0aRU1NDQBVVVUMGTKEoUOHAltPP2pZy1rWspa1rGUtZ3u59Xl9fT2dcvesPYBj\ngCcSlq8AJnSw7T3A6Sn25dn07LPPKk95eZelPOUpr3jygnxsxZAXr1uS1jQlnZdrXWousJ+ZDTKz\ncuBs4LEU2+s+PCIiIhJoubq0xS/YemmLG81sEjDX3f9sZkcCDwNVwGZgubsfkmQ/nu2xi4iIiOyI\nvLrOWFdRMSYiIiKFIm+uM1bIEhvylKe8fMlSnvKUVzx5QT62YshLRcWYiIiISA5pmlJEREQkwzRN\nKSIiIpKnVIylKehz2corzCzlKU95xZMX5GMrhrxUVIyJiIiI5JB6xkREREQyTD1jIiIiInlKxVia\ngj6XrbzCzFKe8pRXPHlBPrZiyEtFxZiIiIhIDqlnTERERCTD1DMmIiIikqdUjKUp6HPZyivMLOUp\nT3nFkxfkYyuGvFRUjImIiIjkkHrGRERERDJMPWMiIiIieUrFWJqCPpetvMLMUp7ylFc8eUE+tmLI\nS0XFmIiIiEgOqWdMREREJMPUMyYiIiKSp1SMpSnoc9nKK8ws5SlPecWTF+RjK4a8VFSMiYiIiOSQ\nesZEREREMkw9YyIiIiJ5KuvFmJkNM7P5ZrbAzCYkeb3czGaZ2btmNsfMBmZ7jMkEfS5beYWZpTzl\nKa948oJ8bMWQl0pWizEzKwHuAE4GDgaGm9kBbTY7D/j/7d17sF1lfcbx7wMnYEAIV0kxBaSCKBQU\nbUgBDRXKxBswFWa4tAboZepoSXEUQZwBLK1AUeI4wx/aADaUikS0YLlIuFgtJhAhCQkpxoZAQkwI\ngUgYLoXw6x/vezKLnb332TlnvXufy/OZ2ZO913r3etY6We973rMu73o+Ig4CZgJXdXMdW1m4cKHz\nnDfsspznPOeNnbzRvG1jIa+dbh8Zmwwsj4inIuJ14PvAyQ1lTga+l9/PAY7v4vq1tHHjRuc5b9hl\nOc95zhs7eaN528ZCXjvd7oy9E1hV+bw6T2taJiI2Axsl7dGd1TMzMzPrrm53xprdRdB4S2RjGTUp\n03UrV650nvOGXZbznOe8sZM3mrdtLOS109WhLSRNAS6NiGn584VARMSVlTJ35jLzJW0P/DYi3tFk\nWT3voJmZmZl1qtXQFn1dXo+HgXdL2h/4LXA6cEZDmduB6cB84DTgvmYLarVBZmZmZiNJVztjEbFZ\n0ueBn5JOkc6KiGWSLgMejoifALOA2ZKWAxtIHTYzMzOzUWnEjsBvZmZmNhqMuBH4JV0laZmkhZJ+\nKGnXyryL8mCxyySdWFPeqZKWSNos6cjK9D5JN0haLGlpvv6tSFaed7ikB/P8RZJ2KJmX5+8naZOk\nLww1q12epBMkLcjb9bCkPymZl+fVvq80LP+IPGjxo5IekvShujOaZP5dHlD5MUlXlM7LmV+U9Gbp\nO57b1fuac9oOSl1z1iRJ90l6PP+fnVcyL2duJ+kRSbd1IWuCpFvy/9tSSUcVzjs/1/fFkv6tjjay\nYfmzJK2TtLgybXdJP5X0hKS7JU0onFesHjTLq8yrvZ63yivVjrX4eXa9nW4pIkbUCzgB2C6/vwL4\nen7/PuBR0qnXA4DfkI/8DTHvPcBBpGvXjqxMPwO4Kb8fDzwJ7Fcoa3tgEXBY/rx7yW2rzJ8D3Ax8\noab/u1bbdwQwMb8/FFhdOO+9JfaVhuy7gRPz+48B99e5/CZ5x5FO//flz3uVzMsZk4C78r6/R+Gs\npvW+5ozt8r6wPzAOWAgcUnCbJgLvz+/fDjxRMi/nnA/cCNzWhf3jBuCc/L4P2LVg1r7ACmCH/Plm\n4DM1ZxwLvB9YXJl2JXBBfv9l4IrCecXqQbO8PL1IPW+xfcXasRZ5XW2n271G3JGxiJgbEW/mj/NI\nOwrAScD3I+KNiFgJLCcNMjvUvCciYjlbD7kRwM5Kd3zuBLwGvFgo60RgUUQsyeVeiLz3FMpD0snA\n/wJLh5ozUF5ELIqItfn9UmBHSeNK5ZEGFq59X2nwJtD/V/JuwDM1L7/RZ0m/CN4AiIjnCucBXAN8\nqQs57ep9nToZlLo2EbE2Ihbm9y8By9h63MXaSJoEfBz4l1IZlaxdgA9HxPUAua4NqX3swPakNrmP\n1CavqXPhEfEL4IWGydVByr8HnFIyr2Q9aLF9UKiet8gr1o61yOt2O93SiOuMNTgXuCO/bxxQ9hkK\nNmyko0Yvk+4KXQlcHRGlhvM9GEDSXfl0XtFfgJJ2Ai4ALqP52HAls08FHs2/DEvpxr5yPnC1pKdJ\nj/S6qOblNzoY+IikeZLuL324XdKngFUR8VjJnBbOBe4ssNxOBqUuQtIBpL/a5xeM6f+l2o0LhQ8E\nnpN0fT4t+h1J40uFRcQa4BvA06T6vDEi5pbKq3hHRKzL67AW2LsLmf1K1YMtelDPu9qO0f12uqVu\nD23REUn3APtUJ5EakIsj4vZc5mLg9Yj490qZRh01Op3kNTEZeIN0qmFP4OeS5uYjLXVn9QHHAB8C\nXgXulbQgIu5vu2GDz7sMuCYiXpbU/52ODDKv/7uHAl8H/rRw3qD3lU6zSacTZkTEj3MH8zq2Ybu2\nMe+rpH1kt4iYIumPgB+QfiGWyvsKb92eIXfat7He3zTUvGar0GRa8Y6LpLeT/ribkY+Qlcj4BLAu\nIhZKOo7yf2T1AUcCn4uIBZJmAhcCl5QIk7Qb6SjV/sDvgDmSziy0n/Rc4XrQnzGe1JbVWs8HUHs7\nNoDPUnM7PVjDsjMWEW1/GJKmkw63f7QyeTXw+5XPk+jwMPVAeS2cCdyVDxmvl/TfpM7SygJZq4Gf\nRcQLAJLuIDV0A3bGBpl3FPBpSVeRrk/bLOmViLi2UF7/KZRbgb8YqENbQ96g95VOsyXNjogZudwc\nSbO2eS23Le9vST8/IuLhfLHtnhGxoe48SYeRrrVbpNRbnwT8StLkiHi27rxKbrN6X6fVwH6Vz4Pa\nL7ZFPqU2B5gdEf9RMOoY4CRJHydd47qLpH+NiM8UyltNOqKyIH+eQ7qmqpQTgBUR8TyApFuBo4HS\nnbF1kvaJiHWSJgKD3v871YV60O8PKFDPB7CKmtuxAUyvu50erBF3mlLSNNIptJMi4rXKrNuA0yXt\nIOldwLuBh+qOr7x/mlwZJO0MTAH+p1DW3cDhkt6WG++pwOM1Zr0lLyI+EhEHRsSBwEzgnzrpiA02\nL9+B9BPgwoiYV3POVnl0Z195RtJUAEnHA7+uefmNfgwcn/MOBsaVasAiYklETMz7yLtIv3g/ULCB\nblfv67RlUGqlO/FOJ+0rJV0HPB4R3yoZEhFfiYj9cp0+HbivYEeMfOpuVd4XIe2bdbdZVU8DU3Ib\nqZy3rECO2LotOTu/nw7U3aF+S14X6sGWvC7V88afZ+l2rDGv2+10a9GjOwcG+yJdbP0U8Eh+XVuZ\ndxHpbqhl5Dskasg7hdRbf4V0fdidefrOpEOoS/JryHcctsrK887MOYup6Q6adnmVMpfUsW0D/Cwv\nBjbl/89H879DvotmgJ9n7ftKQ/bRwIK8Pb8kNWIl68U4YDbwWM6dWjKvIXsF5e+mbFnva86ZRrqr\ncTnpj4OS23QMsJl012b/fj+tC/9fU+nO3ZRHkDq4C0lHOyYUzrsk1+fFpIvpx9W8/JtIR0pfI3X+\nziGdOZib95l7SKfYSuYVqwfN8hrm11rPW2xfX6l2rEVeV9vpdi8P+mpmZmbWQyPuNKWZmZnZaOLO\nmJmZmVkPuTNmZmZm1kPujJmZmZn1kDtjZmZmZj3kzpiZmZlZD7kzZmY2AElnS2r7rENJ35Y04FMx\nGr6zt6RnJe07tDU0s5HMnTEzG5Yk7SXpWklPSnpV0lpJ9+SRsvvLPJAfmXJmw3enS9pU+Tw1l+t/\nPSfpXklHd7Ae44B/AC7tYLW3DNyYH5JdzVwv6XZJ79lSOGI9aYDSr3WwbDMbpdwZM7Ph6lbS817P\nAQ4CPgHcCexZKROkJyxcnjtNNMxr/PxeYCJpFPr1wH9K2muA9TgNeCUifjGIbeh/+PlE0gOIx5Of\nvVdxA3BWfti1mY1B7oyZ2bCTn1d6LOmRRA9ExKqI+FVEfDMiftBQ/GbgbcDnOlj0+oh4NiKWApcD\nE4CjBvjOGTQ8o1LSdpKulvS8pA2SrgG2b/Ld1yKiP3MhcA1wiKQd+wvkdVkD/FkH629mo5A7Y2Y2\nHL2UXydVOy5tyn4N+KqkXQcoKwBJOwHnko6WvT7Ad44lPb+u6ovAXwJ/DfwxqSN2VttgaRfSQ7oX\nx9YPeX6IdLTOzMYgd8bMbNiJiM3AdODPgY2SHpT0z5Imt/jKd4ENwIVtFivgyXwt2Sbg70kPsr63\n5RfSEboJpAfNV80AroyIH0bEr/PntU0W8TFJm3Lm74AP07zTtgY4oM26m9ko5s6YmQ1LEfEjYF/g\nk8AdpCNQ8yRt1eHKnbeLgfPa3JkYwHHAB0hHqFYAZ+fvtjI+//tq/4R89O33gHmV/ADmN/n+z4DD\ngSOAycB9wD2S3tlQ7pVKlpmNMe6MmdmwFRH/FxH3RsTlEXEsMAu4VFJfk7JzgMdof2fiyoj4TUTc\nksv9qMmF/1UbSJ243Qe5CS9HxJMRsSIiFgB/BewK/E1DuT1INxSY2RjkzpiZjSTLgD7SBfvNfJl0\nevPQDpY1GxhHmwv/I+J14HHgfZVpL5JOW05pKN7qFGqjN4GdGqYdBjzS4ffNbJRxZ8zMhh1Je+Rx\nwM6S9IeSDpB0GvAlYG5EvNTsexHxX8BdwOebLbahbAAzgYsktTtFeDfpIv6qbwEXSPq0pIMlzSSd\numy0o6R98usQ4NvAzlTuzszZHyQN22FmY5A7Y2Y2HL0E/BI4D3gAWEIaiuJG0vVe/RrHEoN0Ef+4\nJvOalb2OdCfkjDbr8l1gWsM4YN8Ars/z5pE6ejc2+e4JpIvz1+RyHwROjYifV8qcAjwVEQ+2WQcz\nG8WU/jg0M7NWJN0ELI2Ifyyw7PnANyPi5rqXbWYjg4+MmZkN7ALgxboXKmlv4BZ3xMzGNh8ZMzMz\nM+shHxkzMzMz6yF3xszMzMx6yJ0xMzMzsx5yZ8zMzMysh9wZMzMzM+shd8bMzMzMesidMTMzM7Me\n+n9d7xel6xS4WQAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f106bbeb5f8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.style.use('classic')\n",
    "%matplotlib inline\n",
    "\n",
    "acc_test = sorted(acc_test.items())\n",
    "new_acc = []\n",
    "for i in range(len(acc_test)):\n",
    "    new_acc.append(acc_test[i][1])\n",
    "acc_test_values = new_acc \n",
    "\n",
    "fig1 = plt.figure(figsize=(10, 6), dpi=100)\n",
    "x = snrs\n",
    "y = list(acc_test_values)\n",
    "plt.plot(x, y, marker=\"o\", linewidth=2.0, linestyle='dashed', color='royalblue')\n",
    "plt.axis([-20, 20, 0, 1])\n",
    "plt.xticks(np.arange(min(x), max(x)+1, 2.0))\n",
    "plt.yticks(np.arange(0, 1, 0.10))\n",
    "\n",
    "ttl = plt.title('SNR vs Accuracy', fontsize=16)\n",
    "ttl.set_weight('bold')\n",
    "plt.xlabel('SNR (dB)', fontsize=14)\n",
    "plt.ylabel('Test accuracy', fontsize=14)\n",
    "plt.grid()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:tensorflow:Restoring parameters from ./DNN4layer_regtech_l2\n",
      "Confusion Matrix\n",
      "       8PSK  BPSK  CPFSK  GFSK  PAM4  QAM16  QAM64  QPSK\n",
      "8PSK   0.83  0.00   0.00  0.00  0.00   0.09   0.08   0.0\n",
      "BPSK   0.00  0.99   0.00  0.00  0.00   0.00   0.01   0.0\n",
      "CPFSK  0.01  0.01   0.94  0.00  0.00   0.02   0.02   0.0\n",
      "GFSK   0.02  0.00   0.01  0.95  0.00   0.00   0.01   0.0\n",
      "PAM4   0.00  0.01   0.00  0.00  0.98   0.01   0.00   0.0\n",
      "QAM16  0.07  0.00   0.00  0.00  0.00   0.51   0.43   0.0\n",
      "QAM64  0.01  0.00   0.00  0.00  0.00   0.47   0.52   0.0\n",
      "QPSK   0.04  0.00   0.00  0.00  0.01   0.03   0.02   0.9\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f10646e2e10>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Confusion Matrix\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    saver.restore(sess, path)\n",
    "    Z = logits.eval(feed_dict = {X : X_32test_std[18]})\n",
    "    predicted_18dB = np.argmax(Z, axis = 1)\n",
    "    \n",
    "from sklearn.metrics import confusion_matrix\n",
    "%matplotlib inline\n",
    "\n",
    "classes = ['8PSK', 'BPSK', 'CPFSK', 'GFSK', 'PAM4', 'QAM16', 'QAM64', 'QPSK']\n",
    "conf_matrix = confusion_matrix(predicted_18dB, y_32_test[18])  \n",
    "\n",
    "conf_matrix = conf_matrix.astype('float') / conf_matrix.sum(axis=1)[:, np.newaxis]\n",
    "conf_matrix = conf_matrix.round(decimals = 2)\n",
    "\n",
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame(data = conf_matrix, columns = classes, index = classes) \n",
    "print(\"Confusion Matrix\")\n",
    "print(df)\n",
    "\n",
    "fig1 = plt.figure(figsize=(10, 6), dpi=100)\n",
    "plt.imshow(conf_matrix, interpolation = 'nearest', cmap = plt.cm.Purples)\n",
    "ticks = np.arange(len(classes))\n",
    "plt.title(\"Confusion Matrix\")\n",
    "plt.xticks(ticks, classes, rotation=45)\n",
    "plt.yticks(ticks, classes)\n",
    "\n",
    "plt.ylabel('True class')\n",
    "plt.xlabel('Predicted class')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.colorbar()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  },
  "widgets": {
   "state": {},
   "version": "1.1.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
